package com.bookstore.back.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bookstore.back.dto.LoginDTO;
import com.bookstore.back.dto.RegisterDTO;
import com.bookstore.back.entity.Role;
import com.bookstore.back.entity.User;
import com.bookstore.back.mapper.RoleMapper;
import com.bookstore.back.mapper.UserMapper;
import com.bookstore.back.service.AuthService;
import com.bookstore.back.service.UserLogService;
import com.bookstore.back.util.RequestUtil;
import com.bookstore.back.vo.LoginVO;
import com.bookstore.back.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

/**
 * 认证服务实现类
 * 
 * @author 程序猿_Ti
 * @since 2025-07-16
 */
@Slf4j
@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private UserLogService userLogService;

    // 内存中存储token信息，生产环境建议使用Redis
    private final Map<String, TokenInfo> tokenStore = new ConcurrentHashMap<>();

    // Token信息内部类
    private static class TokenInfo {
        private final Long userId;
        private final String userType;
        private final LocalDateTime createTime;
        private final LocalDateTime expireTime;

        public TokenInfo(Long userId, String userType) {
            this.userId = userId;
            this.userType = userType;
            this.createTime = LocalDateTime.now();
            this.expireTime = LocalDateTime.now().plusHours(24); // 24小时过期
        }

        public boolean isExpired() {
            return LocalDateTime.now().isAfter(expireTime);
        }

        public Long getUserId() { return userId; }
        public String getUserType() { return userType; }
        public LocalDateTime getCreateTime() { return createTime; }
        public LocalDateTime getExpireTime() { return expireTime; }
    }

    @Override
    public LoginVO login(LoginDTO loginDTO) {
        log.info("用户登录，用户名：{}，用户类型：{}", loginDTO.getUsername(), loginDTO.getUserType());

        // 查询用户信息
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", loginDTO.getUsername());
        User user = userMapper.selectOne(queryWrapper);

        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 验证密码（明文比较，按用户要求不加密）
        if (!loginDTO.getPassword().equals(user.getPassword())) {
            throw new RuntimeException("密码错误");
        }

        // 检查用户状态
        if (user.getStatus() == 0) {
            throw new RuntimeException("账户已被禁用");
        }

        // 查询用户角色
        String userType = "user"; // 默认用户类型
        if (user.getRoleId() != null) {
            Role role = roleMapper.selectById(user.getRoleId());
            if (role != null) {
                userType = role.getRoleCode();
            }
        }

        // 验证用户类型是否匹配
        if (!loginDTO.getUserType().equals(userType)) {
            throw new RuntimeException("用户类型不匹配");
        }

        // 构建返回结果
        LoginVO loginVO = new LoginVO();
        
        // 生成简单token（按用户要求不使用JWT）
        String token = "token_" + user.getId() + "_" + System.currentTimeMillis();
        loginVO.setToken(token);

        // 存储新token（允许同一用户多个token，支持多标签页登录）
        tokenStore.put(token, new TokenInfo(user.getId(), userType));

        // 构建用户信息
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        userVO.setUserType(userType);
        loginVO.setUser(userVO);

        // 记录登录日志
        try {
            // 获取当前请求的HttpServletRequest
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                String ipAddress = RequestUtil.getClientIpAddress(request);
                String userAgent = RequestUtil.getUserAgent(request);
                userLogService.recordLoginLog(user.getId(), ipAddress, userAgent);
            } else {
                userLogService.recordLoginLog(user.getId(), "unknown", "unknown");
            }
        } catch (Exception e) {
            log.warn("记录登录日志失败：{}", e.getMessage());
            // 不影响登录流程，只记录警告日志
        }

        log.info("用户登录成功，用户ID：{}，用户类型：{}", user.getId(), userType);
        return loginVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserVO register(RegisterDTO registerDTO) {
        log.info("用户注册，用户名：{}，邮箱：{}，用户类型：{}", 
                registerDTO.getUsername(), registerDTO.getEmail(), registerDTO.getUserType());

        // 验证确认密码
        if (!registerDTO.getPassword().equals(registerDTO.getConfirmPassword())) {
            throw new RuntimeException("两次输入的密码不一致");
        }

        // 检查用户名是否已存在
        if (!checkUsername(registerDTO.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }

        // 检查邮箱是否已存在
        if (!checkEmail(registerDTO.getEmail())) {
            throw new RuntimeException("邮箱已被注册");
        }

        // 检查手机号是否已存在
        if (!checkPhone(registerDTO.getPhone())) {
            throw new RuntimeException("手机号已被注册");
        }

        // 创建用户
        User user = new User();
        user.setUsername(registerDTO.getUsername());
        user.setPassword(registerDTO.getPassword()); // 明文存储，按用户要求不加密
        user.setEmail(registerDTO.getEmail());
        user.setPhone(registerDTO.getPhone());
        user.setBalance(BigDecimal.ZERO);
        user.setStatus(1); // 正常状态
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());

        int result = userMapper.insert(user);
        if (result <= 0) {
            throw new RuntimeException("用户注册失败");
        }

        // 分配角色
        Role role = roleMapper.selectByRoleCode(registerDTO.getUserType());
        if (role == null) {
            throw new RuntimeException("用户类型不存在");
        }

        // 直接设置用户的角色ID
        user.setRoleId(role.getId());
        userMapper.updateById(user);

        // 构建返回结果
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        userVO.setUserType(registerDTO.getUserType());

        log.info("用户注册成功，用户ID：{}，用户类型：{}", user.getId(), registerDTO.getUserType());
        return userVO;
    }

    @Override
    public boolean checkUsername(String username) {
        int count = userMapper.checkUsernameExists(username);
        return count == 0;
    }

    @Override
    public boolean checkEmail(String email) {
        int count = userMapper.checkEmailExists(email);
        return count == 0;
    }

    @Override
    public boolean checkPhone(String phone) {
        int count = userMapper.checkPhoneExists(phone);
        return count == 0;
    }

    @Override
    public UserVO validateToken(String token) {
        if (token == null || token.trim().isEmpty()) {
            return null;
        }

        // 清理过期token
        tokenStore.entrySet().removeIf(entry -> entry.getValue().isExpired());

        TokenInfo tokenInfo = tokenStore.get(token);
        if (tokenInfo == null || tokenInfo.isExpired()) {
            return null;
        }

        // 根据token中的用户ID查询用户信息
        User user = userMapper.selectById(tokenInfo.getUserId());
        if (user == null || user.getStatus() == 0) {
            // 用户不存在或被禁用，移除token
            tokenStore.remove(token);
            return null;
        }

        // 构建用户信息
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        userVO.setUserType(tokenInfo.getUserType());

        log.debug("Token验证成功，用户ID：{}，用户类型：{}", user.getId(), tokenInfo.getUserType());
        return userVO;
    }

    @Override
    public boolean logout(String token) {
        if (token == null || token.trim().isEmpty()) {
            return false;
        }

        TokenInfo tokenInfo = tokenStore.remove(token);
        if (tokenInfo != null) {
            log.info("用户登出成功，用户ID：{}", tokenInfo.getUserId());
            return true;
        }

        return false;
    }

}
